#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>

#define PAGE_SIZE 4096

uint64_t get_physical_address(pid_t pid, void *vaddr) {
    char pagemap_file[256];
    snprintf(pagemap_file, sizeof(pagemap_file), "/proc/%d/pagemap", pid);
    
    int fd = open(pagemap_file, O_RDONLY);
    if (fd < 0) {
        perror("open pagemap");
        return -1;
    }

    // 计算虚拟页号
    unsigned long virtual_page = ((unsigned long)vaddr) / PAGE_SIZE;
    uint64_t entry;
    
    // 读取对应虚拟页的pagemap条目
    ssize_t bytes_read = pread(fd, &entry, sizeof(entry), virtual_page * sizeof(entry));
    if (bytes_read != sizeof(entry)) {
        perror("pread");
        close(fd);
        return -1;
    }

    close(fd);

    // 检查页面是否存在
    if (!(entry & (1ULL << 63))) {
        fprintf(stderr, "Page not present");
        return -1;
    }

    // 获取物理页号
    uint64_t page_frame_number = entry & ((1ULL << 55) - 1);
    uint64_t physical_address = (page_frame_number * PAGE_SIZE) + ((unsigned long)vaddr) % PAGE_SIZE;

    return physical_address;
}

int main() {
    int a = 10;
    printf("Logical address of a: %p \n", (int*)&a);

    pid_t pid = getpid();
    uint64_t phys_addr = get_physical_address(pid, &a);
    if (phys_addr != (uint64_t)-1) {
        printf("Physical address of a: 0x%llx\n", phys_addr);
    } else {
        printf("Failed to get physical address of a.");
    }

    return 0;
}
